package net.xt.testthread;

import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

public class TestCompletableThread {

    public static void main(String[] args) throws InterruptedException {
//        test1();
        test2();

//        List<Integer> list = new ArrayList<>();
//        for (int i = 0; i < 10; i++) {
//            list.add(i);
//        }
//        test3(list);
    }

    private static void test1() throws InterruptedException {
        ExecutorService threadPool = Executors.newFixedThreadPool(3);

        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "自定义线程1");
        }, threadPool);

        CompletableFuture<Void> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return Thread.currentThread().getName() + "自定义线程2";
        }, threadPool).thenAccept((result) -> {
            System.out.println(result);
        });
        // 关闭线程池
        threadPool.shutdown();

        System.out.println(Thread.currentThread().getName() + "------主线程");

        try {
            CompletableFuture.allOf(future1, future2).get();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("===========全部线程执行完成");
    }

    private static void test2() {
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        CompletableFuture<Integer> exceptionally = CompletableFuture.supplyAsync(() -> {
                    System.out.println(Thread.currentThread().getName() + "---come in");

                    int result = 0;
                    try {
                        while (true) {
                            TimeUnit.SECONDS.sleep(1);
                            result = ThreadLocalRandom.current().nextInt(10);
                            System.out.println("----------1秒钟后出结果" + result);
                            if (result == 5) {
                                //模拟产生异常情况
//                                int i = 10 / 0;
                                break;
                            }
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    return result;
                }, executorService)
                .whenComplete((res, throwable) -> {
                    if (throwable == null) {
                        System.out.println("计算完成 更新系统" + res);
                    }
                })
                .exceptionally(e -> {
                    e.printStackTrace();
                    System.out.println("异常情况：" + e.getCause() + " " + e.getMessage());
                    return null;
                });

        // join会阻断CompletableFuture执行完返回结果，再执行后续代码
//        System.out.println("exceptionally = " + exceptionally.join());
        // 关闭线程池
        executorService.shutdown();

        System.out.println(Thread.currentThread().getName() + "先去完成其他任务");
    }

    private static void test3(List<Integer> list) {
        long startTime = System.currentTimeMillis();
        list.stream()
                .map(i -> {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (i % 2 == 0) {
                        return i + "偶数";
                    } else {
                        return i + "奇数";
                    }
                })
                .collect(Collectors.toList());
        long endTime = System.currentTimeMillis();
        System.out.println("======================耗时" + (endTime - startTime) + "毫秒");

        long startTime2 = System.currentTimeMillis();
        list.stream()
                .map(item ->
                        CompletableFuture.supplyAsync(() -> {
                            try {
                                TimeUnit.SECONDS.sleep(1);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            String result = "";
                            if (item % 2 == 0) {
                                result = item + "偶数";
                            } else {
                                result = item + "奇数";
                            }
                            return result;
                        }))
                .collect(Collectors.toList())
                .stream()
                .map(future -> future.join())
                .collect(Collectors.toList());
        long endTime2 = System.currentTimeMillis();
        System.out.println("=====================耗时" + (endTime2 - startTime2) + "毫秒");
    }

}
